from django.conf import settings
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone


class CustomOssStorage:
    """延迟初始化的存储后端"""
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            from .oss_storage import CustomOssStorage as StorageClass
            cls._instance = StorageClass()
        return cls._instance

class CustomUser(AbstractUser):
    """扩展的用户模型"""
    USER_TYPE_CHOICES = (
        ('normal', '普通用户'),
        ('organizer', '活动组织者'),
    )

    email = models.EmailField(unique=True)
    phone = models.CharField(max_length=15, unique=True, null=True, blank=True)
    avatar = models.ImageField(
        upload_to='avatars/',
        null=True,
        blank=True,
        storage=CustomOssStorage()
    )
    bio = models.TextField(max_length=500, blank=True, verbose_name='个性签名')
    interests = models.CharField(max_length=200, blank=True, verbose_name='兴趣标签')
    user_type = models.CharField(max_length=10, choices=USER_TYPE_CHOICES, default='normal')
    points = models.IntegerField(default=0, verbose_name='积分')
    location = models.CharField(max_length=100, blank=True, verbose_name='所在地')
    latitude = models.FloatField(null=True, blank=True)
    longitude = models.FloatField(null=True, blank=True)

    # 隐私设置
    show_email = models.BooleanField(default=False, verbose_name='公开邮箱')
    show_phone = models.BooleanField(default=False, verbose_name='公开手机号')
    show_location = models.BooleanField(default=True, verbose_name='公开位置')

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    # 积分相关字段
    total_points_earned = models.IntegerField(default=0, verbose_name='总获得积分')
    level = models.IntegerField(default=1, verbose_name='等级')
    experience = models.IntegerField(default=0, verbose_name='经验值')

    # 统计字段
    consecutive_login_days = models.IntegerField(default=0, verbose_name='连续登录天数')
    last_login_date = models.DateField(null=True, blank=True, verbose_name='最后登录日期')

    def add_points(self, points, source_type, description, related_event=None, related_post=None):
        """添加积分 - 使用字符串导入避免循环依赖"""
        from Location.models import PointRule, PointTransaction

        # 检查积分规则
        try:
            rule = PointRule.objects.get(rule_type=source_type, is_active=True)

            # 检查每日上限
            if rule.daily_limit > 0:
                today = timezone.now().date()
                today_count = PointTransaction.objects.filter(
                    user=self,
                    source_type=source_type,
                    created_at__date=today
                ).count()
                if today_count >= rule.daily_limit:
                    return False, "今日已达到该类型积分上限"

            points_to_add = rule.points

        except PointRule.DoesNotExist:
            points_to_add = points

        # 创建交易记录
        transaction = PointTransaction.objects.create(
            user=self,
            transaction_type='earn',
            points=points_to_add,
            source_type=source_type,
            description=description,
            related_event=related_event,
            related_post=related_post
        )

        # 更新用户积分
        self.points += points_to_add
        self.total_points_earned += points_to_add  # 确保总获得积分正确更新

        # 计算经验值（1积分 = 1经验值）
        self.experience += points_to_add

        # 更新等级（每1000经验值升一级）
        new_level = max(1, self.experience // 1000 + 1)
        if new_level > self.level:
            self.level = new_level

        self.save()
        return True, f"获得 {points_to_add} 积分"

    def spend_points(self, points, source_type, description, related_event=None, related_post=None):
        """消费积分"""
        if self.points < points:
            return False, "积分不足"

        # 创建交易记录
        from Location.models import PointTransaction
        transaction = PointTransaction.objects.create(
            user=self,
            transaction_type='spend',
            points=points,
            source_type=source_type,
            description=description,
            related_event=related_event,
            related_post=related_post
        )

        # 更新用户积分
        self.points -= points
        self.save()
        return True, f"消费 {points} 积分"

    def recalculate_points(self):
        """重新计算用户积分数据"""
        from django.db.models import Sum
        from Location.models import PointTransaction

        # 计算实际总获得积分
        earned_result = PointTransaction.objects.filter(
            user=self,
            transaction_type__in=['earn', 'refund']
        ).aggregate(total=Sum('points'))
        total_earned = earned_result['total'] or 0

        # 计算实际总消费积分
        spent_result = PointTransaction.objects.filter(
            user=self,
            transaction_type='spend'
        ).aggregate(total=Sum('points'))
        total_spent = spent_result['total'] or 0

        # 更新用户数据
        self.total_points_earned = total_earned
        self.points = total_earned - total_spent
        self.experience = total_earned  # 经验值等于总获得积分
        self.level = max(1, self.experience // 1000 + 1)

        self.save()
        return True

    def __str__(self):
        return self.username

    @property
    def avatar_url(self):
        """获取头像URL，如果没有头像则返回默认头像"""
        if self.avatar and hasattr(self.avatar, 'name') and self.avatar.name:
            try:
                return self.avatar.storage.url(self.avatar.name)
            except Exception as e:
                print(f"获取头像URL错误: {e}")
                return f"{settings.MEDIA_URL}{self.avatar.name}"

        return getattr(settings, 'DEFAULT_AVATAR_URL', '/static/images/default-avatar.png')

    def get_avatar_url(self):
        """安全获取头像URL的方法"""
        if self.avatar and hasattr(self.avatar, 'url'):
            return self.avatar.url
        return getattr(settings, 'DEFAULT_AVATAR_URL', '/static/images/default-avatar.png')

    def save(self, *args, **kwargs):
        if not self.pk and not self.avatar:
            self.avatar = 'avatars/head.jpg'
        super().save(*args, **kwargs)


class UserProfile(models.Model):
    """用户详细资料"""
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, related_name='profile')
    gender = models.CharField(max_length=10, choices=(('male', '男'), ('female', '女')), blank=True)
    birth_date = models.DateField(null=True, blank=True)
    occupation = models.CharField(max_length=50, blank=True)
    wechat_id = models.CharField(max_length=50, blank=True)

    # 社交统计
    followers_count = models.IntegerField(default=0)
    following_count = models.IntegerField(default=0)
    events_attended = models.IntegerField(default=0)
    events_organized = models.IntegerField(default=0)

    def __str__(self):
        return f"{self.user.username}的个人资料"


class Follow(models.Model):
    """用户关注关系"""
    follower = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='following')
    following = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='followers')
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('follower', 'following')


class PrivateMessage(models.Model):
    """私信"""
    sender = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='sent_messages')
    receiver = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='received_messages')
    content = models.TextField()
    is_read = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']
